package com.xnyzc.lhy.order.service.impl.cms.util;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.xnyzc.lhy.common.component.config.GlobalConfig;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.dept.EOffIceType;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.order.entity.cms.OaSysRole;
import com.xnyzc.lhy.order.entity.cms.OaSysRoleOffice;
import com.xnyzc.lhy.order.entity.sidebar.OaCUserOffice;
import com.xnyzc.lhy.mis.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.order.entity.system.OaSysUser;
import com.xnyzc.lhy.order.entity.system.OaSysUserOffice;
import com.xnyzc.lhy.order.entity.system.OaSysUserRole;
import com.xnyzc.lhy.order.entity.user.OaDUserOffice;
import com.xnyzc.lhy.order.mapper.cms.OaSysRoleMapper;
import com.xnyzc.lhy.order.mapper.cms.util.OaSysGetOfficeIdListMapper;
import com.xnyzc.lhy.order.mapper.sidebar.OaCUserOfficeMapper;
import com.xnyzc.lhy.order.mapper.sidebar.OaSysOfficeMapper;
import com.xnyzc.lhy.order.mapper.system.OaSysUserMapper;
import com.xnyzc.lhy.order.mapper.system.OaSysUserOfficeMapper;
import com.xnyzc.lhy.order.mapper.system.OaSysUserRoleMapper;
import com.xnyzc.lhy.order.mapper.user.OaDUserOfficeMapper;
import com.xnyzc.lhy.order.service.cms.util.IOaSysGetOfficeIdListService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @Description 获取当前用户可查询的机构
 * @Author zhuyubin
 * @Date 2019-08-21 19:51
 **/
@Service
public class OaSysGetOfficeIdListServiceImpl implements IOaSysGetOfficeIdListService {

    @Autowired
    private OaSysUserMapper oaSysUserMapper;
    @Autowired
    private OaSysOfficeMapper oaSysOfficeMapper;
    @Autowired
    private OaSysUserOfficeMapper oaSysUserOfficeMapper;
    @Autowired
    private OaCUserOfficeMapper oaCUserOfficeMapper;
    @Autowired
    private OaDUserOfficeMapper oaDUserOfficeMapper;
    @Autowired
    private OaSysUserRoleMapper oaSysUserRoleMapper;
    @Autowired
    private OaSysRoleMapper oaSysRoleMapper;
    @Autowired
    private OaSysGetOfficeIdListMapper oaSysGetOfficeIdListMapper;

    /**
     * 获取当前角色可查看部门
     * @param sysUserId 用户id
     * @return
     */
    @Override
    public List<Long> selectOfficeIdList(Long sysUserId){
        QueryWrapper queryWrapper = this.dataScopeFilter(sysUserId, "oso", "osu");
        List<Long> officeIds = oaSysGetOfficeIdListMapper.selectOfficeList(queryWrapper);
        return officeIds;
    }

    /**
     * 根据userId查询可查看的乘客id
     * @param sysUserId 后台用户 id
     * @param type 数据范围
     * @return
     */
    @Override
    public List<Long> selectCUserIdList(Long sysUserId, List<String> type){
        LambdaQueryWrapper<OaCUserOffice> wrapper = Wrappers.<OaCUserOffice>lambdaQuery().in(OaCUserOffice::getOfficeId, this.selectOfficeIdList(sysUserId));
        if (type.contains(GlobalConfig.DATA_SCOPE_SELF)){
            wrapper.eq(OaCUserOffice::getUserId, sysUserId);
        }
        List<OaCUserOffice> oaCUserOffices = oaCUserOfficeMapper.selectList(wrapper);
        List<Long> result = new ArrayList<>();
        for (OaCUserOffice oaCUserOffice : oaCUserOffices) {
            result.add(oaCUserOffice.getUserId());
        }
        return result;
    }

    /**
     * 根据userId查询可查看的司机用户id
     * @param sysUserId 后台用户 id
     * @param type 数据范围
     * @return
     */
    @Override
    public List<Long> selectDUserIdList(Long sysUserId, List<String> type){
        LambdaQueryWrapper<OaDUserOffice> wrapper = Wrappers.<OaDUserOffice>lambdaQuery().in(OaDUserOffice::getOfficeId, this.selectOfficeIdList(sysUserId));
        if (type.contains(GlobalConfig.DATA_SCOPE_SELF)){
            wrapper.eq(OaDUserOffice::getDriverId, sysUserId);
        }
        List<OaDUserOffice> oaDUserOffices = oaDUserOfficeMapper.selectList(wrapper);
        List<Long> result = new ArrayList<>();
        for (OaDUserOffice oaDUserOffice : oaDUserOffices) {
            result.add(oaDUserOffice.getDriverId());
        }
        return result;
    }


    /**
     * 根据userId查询可查看的管理员用户id
     * @param sysUserId 后台用户 id
     * @param type 数据范围
     * @return
     */
    @Override
    public List<Long> selectSysUserIdList(Long sysUserId, List<String> type){
        LambdaQueryWrapper<OaSysUserOffice> wrapper = Wrappers.<OaSysUserOffice>lambdaQuery().in(OaSysUserOffice::getOfficeId, this.selectOfficeIdList(sysUserId));
        if (type.contains(GlobalConfig.DATA_SCOPE_SELF)){
            wrapper.eq(OaSysUserOffice::getSysUserId, sysUserId);
        }
        List<OaSysUserOffice> oaSysUserOffices = oaSysUserOfficeMapper.selectList(wrapper);
        List<Long> result = new ArrayList<>();
        for (OaSysUserOffice oaSysUserOffice : oaSysUserOffices) {
            result.add(oaSysUserOffice.getSysUserId());
        }
        return result;
    }

    /**
     * 数据范围过滤 条件
     * @param sysUserId 后台用户 id 当前用户对象，通过“UserUtils.getUser()”获取
     * @param officeAlias 机构表别名，例如：dc.createAlias("office", "office");
     * @param userAlias 用户表别名，传递空，忽略此参数
     * @return 标准连接条件对象
     */
    @Override
    public QueryWrapper dataScopeFilter(Long sysUserId, String officeAlias, String userAlias) {
        // 进行权限过滤，多个角色权限范围之间为或者关系。
        List<String> dataScope = Lists.newArrayList();
        // 条件结果
        QueryWrapper qw = new QueryWrapper();
        // 超级管理员，跳过权限过滤
        OaSysUser oaSysUser = oaSysUserMapper.selectById(sysUserId);
        if (!oaSysUser.getSysUserId().equals(1L)){
            List<OaSysUserRole> oaSysUserRoles = oaSysUserRoleMapper.selectList(Wrappers.<OaSysUserRole>lambdaQuery().eq(OaSysUserRole::getUserId, sysUserId));
            for (OaSysUserRole oaSysUserRole : oaSysUserRoles){
                Long roleId = oaSysUserRole.getRoleId();
                OaSysRole oaSysRole = oaSysRoleMapper.selectById(roleId);
                if (CheckUtil.objIsEmpty(oaSysRole)){
                    continue;
                }
                if (!dataScope.contains(oaSysRole.getDataScope()) && StringUtils.isNotBlank(officeAlias)){
                    String officeId = OaSysOffice.OFFICE_ID;
                    String parentIds = OaSysOffice.PARENT_IDS;
                    String parentId = OaSysOffice.PARENT_ID;
                    String type = OaSysOffice.TYPE;
                    String sysUserIdStr = OaSysUser.SYS_USER_ID;
                    String roleIdStr = OaSysRole.ROLE_ID;
                    String oaSysRoleOfficeOfficeId = OaSysRoleOffice.OFFICE_ID;
                    boolean isDataScopeAll = false;
                    if (GlobalConfig.DATA_SCOPE_ALL.equals(oaSysRole.getDataScope())){
                        isDataScopeAll = true;
                    }
                    else if (GlobalConfig.DATA_SCOPE_COMPANY_AND_CHILD.equals(oaSysRole.getDataScope())){
                        qw.eq(String.format("%s.%s", officeAlias, officeId), oaSysUser.getCompanyId());
                        qw.or();
                        qw.likeRight(String.format("%s.%s", officeAlias, parentIds), this.getParentIds(oaSysUser.getCompanyId()) + oaSysUser.getCompanyId() + ",");
                    }
                    else if (GlobalConfig.DATA_SCOPE_COMPANY.equals(oaSysRole.getDataScope())){
                        qw.eq(String.format("%s.%s", officeAlias, officeId), oaSysUser.getCompanyId());
                        qw.or();
                        qw.eq(String.format("%s.%s", officeAlias, parentId), oaSysUser.getCompanyId());
                        // 包括本公司下的部门
                        qw.eq(String.format("%s.%s", officeAlias, type), EOffIceType.dept.getValue());
                    }
                    else if (GlobalConfig.DATA_SCOPE_OFFICE_AND_CHILD.equals(oaSysRole.getDataScope())){
                        qw.eq(String.format("%s.%s", officeAlias, officeId), oaSysUser.getOfficeId());
                        qw.or();
                        qw.likeRight(String.format("%s.%s", officeAlias, parentIds), this.getParentIds(oaSysUser.getOfficeId()) + oaSysUser.getOfficeId() + ",");
                    }
                    else if (GlobalConfig.DATA_SCOPE_OFFICE.equals(oaSysRole.getDataScope())){
                        qw.eq(String.format("%s.%s", officeAlias, officeId), oaSysUser.getOfficeId());
                    }
                    else if (GlobalConfig.DATA_SCOPE_CUSTOM.equals(oaSysRole.getDataScope())){
                        qw.or();
                        qw.exists(
                                String.format(
                                        "SELECT 1 FROM %s WHERE %s = '%s' AND %s = %s.%s",
                                        "oa_sys_role_office",
                                        roleIdStr,
                                        oaSysRole.getRoleId(),
                                        oaSysRoleOfficeOfficeId,
                                        officeAlias,
                                        officeId
                                ));
                    }
                    //else if (Role.DATA_SCOPE_SELF.equals(r.getDataScope())){
                    if (!isDataScopeAll){
                        if (StringUtils.isNotBlank(userAlias)){
                            qw.or();
                            qw.eq(String.format("%s.%s", userAlias, sysUserIdStr), oaSysUser.getSysUserId());
                        }else {
                            qw.isNull(String.format("%s.%s", officeAlias, officeId));
                        }
                    }else{
                        // 如果包含全部权限，则去掉之前添加的所有条件，并跳出循环。
                        qw = new QueryWrapper();
                        break;
                    }
                    dataScope.add(oaSysRole.getDataScope());
                }
            }
        }
        return qw;
    }

    /**
     * 根据机构获全部取父节点
     * @param officeId
     * @return
     */
    private String getParentIds(Long officeId){
        OaSysOffice oaSysOffice = oaSysOfficeMapper.selectById(officeId);
        if (CheckUtil.objIsEmpty(oaSysOffice)){
            throw PangException.create(EErrorCode.unOffice);
        }
        return oaSysOffice.getParentIds();
    }
}
